/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "渲染.h"

#include "节点数据声明.h"
#include <Context/当前默认操作数据.h>
#include <node后端.h>


#include "A_引擎/文件工程/工程文件.h"


static S_Scene* g渲染任务[128] = {};
static uint32   g渲染任务数量 = 0;
static int32    g延迟 = 0;

static std::thread	g光追渲染线程;
static bool         g有运行线程 = false;

static std::mutex   g_渲染状态锁;


void on_渲染菜单项点击(C_Widget* self, const std::wstring name, uint16 id) {
	if (name == L"渲染单帧") {
		//f_运行渲染节点树();
	}
	else if (name == L"渲染序列") {
		//f_运行渲染节点树();
		//S_节点数据::g_渲染根节点树;
	}
	else if (name == L"渲染重载") {
		auto* scene = f_NodeCtx_get默认场景();
		scene->m_光追后端->f_重载();
	}

}


static void f_渲染任务线程() {
	++S_Engine::g_在运行线程;

	for (; S_Engine::g_渲染线程; ) {
		auto& frame = f_NodeCtx_get帧();

		switch (S_光追后端::g_渲染状态) {
		case E_离线渲染状态::e_光追渲染_单帧:
			g_渲染状态锁.lock();

			S_节点数据::g_渲染帧编号 = f_prop_I32(frame.当前帧);
			f_NodeCtx_set场景当前时间(S_节点数据::g_渲染帧编号);
			S_节点数据::g_开启节点帧更新 = true;

			f_NodeCtx_get默认场景()->f_Update(nullptr);
			f_node_Step节点树();
			S_光追后端::g_渲染状态 = E_离线渲染状态::e_光追渲染_关;
			//std::cout<<"S_框架::g_渲染状态"<<f_prop_I32(frame.当前帧)<<std::endl;
			g_渲染状态锁.unlock();
			break;

		case E_离线渲染状态::e_光追渲染_序列: {
			g_渲染状态锁.lock();

			auto 区间 = f_prop_iVec2(frame.帧区间);
			if (S_节点数据::S_节点数据::g_渲染帧编号 > 区间.y) {
				S_光追后端::g_渲染状态 = E_离线渲染状态::e_光追渲染_关;
			}
			else {
				f_NodeCtx_set场景当前时间(S_节点数据::g_渲染帧编号);

				S_节点数据::g_开启节点帧更新 = true;
				f_NodeCtx_get默认场景()->f_Update(nullptr);
				f_node_Step节点树();
				++S_节点数据::g_渲染帧编号;
			}

			g_渲染状态锁.unlock();
			break;
		}

		case E_离线渲染状态::e_离线计算_序列: {
			g_渲染状态锁.lock();

			auto 区间 = f_prop_iVec2(frame.帧区间);
			if (S_节点数据::S_节点数据::g_渲染帧编号 > 区间.y) {
				S_光追后端::g_渲染状态 = E_离线渲染状态::e_光追渲染_关;
			}
			else {
				f_NodeCtx_set场景当前时间(S_节点数据::g_渲染帧编号);

				S_节点数据::g_开启节点帧更新 = true;
				f_NodeCtx_get默认场景()->f_Update(nullptr);
				f_node_Step节点树();
				++S_节点数据::g_渲染帧编号;
			}

			g_渲染状态锁.unlock();
			break;
		}
		default:
			std::this_thread::sleep_for(std::chrono::milliseconds(g延迟));
			if (g延迟 < 2000) g延迟 += 100;
			break;
		}
	}

	--S_Engine::g_在运行线程;
	g有运行线程 = false;
}

void f_render_加入光追渲染任务线程(E_离线渲染状态 渲染状态) {
	S_光追后端::g_渲染状态 = 渲染状态;
	f_NodeCtx_get默认场景()->m_光追后端->f_重置渲染帧记录();
	//return;
	if (!g有运行线程) {
		g光追渲染线程 = std::thread(f_渲染任务线程);
		g有运行线程 = true;
	}

	g渲染任务数量 = 1;
	g延迟 = 0;
}

void f_render_等待渲染停止() {
	g_渲染状态锁.lock();
	S_光追后端::g_渲染状态 = E_离线渲染状态::e_光追渲染_关;
	g渲染任务数量 = 0;
	g_渲染状态锁.unlock();
}

void f_render_关闭渲染器() {
	S_Engine::g_渲染线程 = false;

	for (uint32 i = 0; i < 100; ++i) {
		if (g有运行线程) {
			std::this_thread::sleep_for(std::chrono::milliseconds(500));
		}
		else {
			break;
		}
	}
}


/*bool f_运行渲染节点树() {
	bool 是否中断 = false;
	for (auto& e : S_节点数据::g_渲染根节点树) {
		e->f_准备Update();
		e->m_开启帧更新 = true;

		uint32 num = e->m_层更新节点.size();
		for (uint32 i = 0; i < num; ++i) {
			if (e->f_Update(i)) {
				e->m_中断层 = i;
				是否中断 = true;
				break;
			}
		}

	}
	return !是否中断;
}*/


